const Vue = require('vue');
const express = require('express');
const fs = require('fs');
const { createBundleRenderer } = require('vue-server-renderer');
const setupDevServer = require('./build/setup-dev-server');

const server = express();
// 这里的dist应该是跟打包出口一致的 处理的是磁盘中的资源文件
server.use('', express.static('./dist'));

/**
 * @serverBundle webpack根据server.config配置文件打包出来的结果
 * @template 
 */
let serverBundle, template, clientManifest, renderer, onReady;

const isProd = process.env.NODE_ENV === 'production';
if (isProd) {
  serverBundle = require('./dist/vue-ssr-server-bundle.json');
  template = fs.readFileSync('./index.template.html', 'utf-8');
  clientManifest = require('./dist/vue-ssr-client-manifest.json');
  // renderer 在调用renderToString的时候会去加载 serverBundle 里面的入口并执行代码
  // 得到 entry-server.js 中创建的 Vue 实例进行渲染
  // 把渲染的结果注入给模板 template
  // 最后把结合后的传给客户端
  renderer = createBundleRenderer(serverBundle, {
    template,
    clientManifest // 客户端接管需要的资源 客户端js
  });
} else {
  // 开发模式 => 监视打包构建 => 重新生成 renderer 渲染器
  onReady = setupDevServer(server, (template, serverBundle, clientManifest) => {
    renderer = createBundleRenderer(serverBundle, {
      template,
      clientManifest // 客户端接管需要的资源 客户端js
    });
  });
}

const render = async (req, res) => {
  try {
    const html = await renderer.renderToString({
      title: 'lanpang',
      meta: `<meta name="description" context="lanpang666">`,
      url: req.url
    });
    res.setHeader('Content-Type', 'text/html; charset=utf8');
    res.end(html);
  } catch (error) {
    return res.status(500).end('Internal Server Error.');
  }
  /**
   * 第1个参数 传给html模板的参数 可以在html模板中用传入的这些变量 也是enter-server.js中拿到的 context对象
   * 第2个参数 通过vue实例渲染出来的html字符串或者是出错的错误信息
   */
  // renderer.renderToString({
  //   title: 'lanpang',
  //   meta: `<meta name="description" context="lanpang666">`,
  //   url: req.url
  // }, (err, html) => {
  //   if (err) {
  //     return res.status(500).end('Internal Server Error.');
  //   }
  //   res.setHeader('Content-Type', 'text/html; charset=utf8');
  //   res.end(html);
  // })
}

// 重要！！！服务端express路由设置为 * 意味着所有的路由都会进入这里
server.get('*', isProd
  ? render
  : async (req, res) => {
    await onReady;
    render(req, res);
  }
);

server.listen(3000, () => {
  console.log('server running');
});

